#pragma once
#ifndef COUNTER_MT_H_
#define COUNTER_MT_H_

#include <cstdio>
#include <mutex>
#include <condition_variable>

class counter_mt
{
private:
    std::mutex mtx;
    std::condition_variable cond;
    unsigned target;
    unsigned counter;
public:
    counter_mt():
        mtx(), cond(), target(0), counter(0) {};
    ~counter_mt()
    {
        std::lock_guard<std::mutex> lck(mtx);
        if (0 < counter && counter < target)
        {
            std::printf("[~counter_mt()]: counter is running, fix it!\n");
        }
    };
    void reset(unsigned new_target)
    {
        std::lock_guard<std::mutex> lck(mtx);
        if (counter < target)
        {
            std::printf("[counter_mt::reset]: counter is running, fix it!\n");
        }
        counter = 0;
        target = new_target;
    };
    void count()
    {
        std::unique_lock<std::mutex> lck(mtx);
        ++counter;
        if (counter >= target)
        {
            cond.notify_all();
        }
        return;
    };
    void wait()
    {
        std::unique_lock<std::mutex> lck(mtx);
        while (counter < target)
        {
            cond.wait(lck);
        }
        return;
    };
};

#endif
